package org.xx.armory.db.impl;

import org.xx.armory.db.Dao;
import org.xx.armory.db.SessionFactory;

import java.util.Arrays;
import java.util.stream.Collectors;

import static org.xx.armory.commons.Validators.notNull;

/**
 * 数据访问对象的基类, 提供了数据访问对象的一些公共方法。
 *
 * @author Haart
 */
public abstract class AbstractDao
        implements Dao {
    private SessionFactory sessionFactory;

    private Object lastRowId;

    protected AbstractDao() {
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final SessionFactory getSessionFactory() {
        return this.sessionFactory;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final void setSessionFactory(
            SessionFactory sessionFactory
    ) {
        this.sessionFactory = notNull(sessionFactory, "sessionFactory");
    }

    /**
     * 获取最后被修改或者插入的行的ID, 参见&lt;autoKey&gt;属性。
     *
     * @return 最后被修改或者插入的行的ID
     */
    public final Object getLastRowId() {
        return this.lastRowId;
    }

    /**
     * 设置最后被修改或者插入的行的ID。
     * <p>
     * <strong>此方法应当由框架内部调用。</strong>
     * </p>
     *
     * @param lastRowId
     *         最后被修改或者插入的行的ID
     */
    protected final void setLastRowId(
            Object lastRowId
    ) {
        this.lastRowId = lastRowId;
    }

    /**
     * 获取以长整数形式返回的最后被修改或者插入的行的ID
     *
     * @return 以长整数形式返回的最后被修改或者插入的行的ID, 如果此ID是{@code null}或者无法被表示为长整数则返回{@code 0}。
     * @see #getLastRowId()
     */
    public final long getLastRowLongId() {
        if (this.lastRowId instanceof Number) {
            return ((Number) this.lastRowId).longValue();
        } else if (this.lastRowId instanceof String) {
            try {
                return Long.parseLong((String) this.lastRowId);
            } catch (NumberFormatException ex) {
                return 0L;
            }
        } else {
            return 0L;
        }
    }

    /**
     * 获取以字符串形式返回的最后被修改或者插入的行的ID
     *
     * @return 以字符串形式返回的最后被修改或者插入的行的ID, 如果此ID是{@code null}则返回空字符串({@code ""})。
     * @see #getLastRowId()
     */
    public final String getLastRowStringId() {
        return this.lastRowId == null ? "" : String.valueOf(this.lastRowId);
    }

    /**
     * 检测此对象的状态是否正确，用于自动生成的字节码。
     *
     * @throws IllegalStateException
     *         如果此对象尚未设置{@code SessionFactory}属性。
     */
    protected final void checkState() {
        if (getSessionFactory() == null) {
            throw new IllegalStateException("this.sessionFactory is not set");
        }
    }

    /**
     * 将字段名数组映射为逗号分隔的列表。
     *
     * @param fieldNames
     *         字段名数组。
     * @return 逗号分隔的列表形式。
     * @throws IllegalArgumentException
     *         如果参数{@code fieldNames}是{@code null}。
     */
    protected final String joinFieldNames(
            String[] fieldNames
    ) {
        notNull(fieldNames, "fieldNames");

        return Arrays.stream(fieldNames)
                     .map(fieldName -> "\"" + fieldName.trim() + "\"")
                     .collect(Collectors.joining(","));
    }

}
